package com.yanxx.codegenerator.storage.impl;

import com.yanxx.codegenerator.storage.CodeGeneratorState;
import com.yanxx.codegenerator.storage.CodeGeneratorStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.HashSet;
import java.util.Set;

/**
 * Redis存储实现
 * 使用Redis存储编号数据
 */
public class RedisStorage implements CodeGeneratorStorage {
    private static final Logger logger = LoggerFactory.getLogger(RedisStorage.class);
    
    private final JedisPool jedisPool;
    private final String keyPrefix;
    
    // Redis中的键名
    private final String currentMaxValueKey;
    private final String confirmedCodesKey;
    private final String pendingCodesKey;
    private final String recycledCodesKey;
    
    /**
     * 构造函数
     *
     * @param jedisPool Redis连接池
     * @param keyPrefix Redis键前缀，用于区分不同的生成器实例
     */
    public RedisStorage(JedisPool jedisPool, String keyPrefix) {
        this.jedisPool = jedisPool;
        this.keyPrefix = keyPrefix;
        
        // 初始化Redis键名
        this.currentMaxValueKey = keyPrefix + ":currentMaxValue";
        this.confirmedCodesKey = keyPrefix + ":confirmedCodes";
        this.pendingCodesKey = keyPrefix + ":pendingCodes";
        this.recycledCodesKey = keyPrefix + ":recycledCodes";
    }
    
    @Override
    public boolean save(long currentMaxValue, Set<String> confirmedCodes, Set<String> pendingCodes, Set<String> recycledCodes) {
        try (Jedis jedis = jedisPool.getResource()) {
            // 保存当前最大值
            jedis.set(currentMaxValueKey, String.valueOf(currentMaxValue));
            
            // 清除并重新保存已确认的编号
            jedis.del(confirmedCodesKey);
            if (confirmedCodes != null && !confirmedCodes.isEmpty()) {
                jedis.sadd(confirmedCodesKey, confirmedCodes.toArray(new String[0]));
            }
            
            // 清除并重新保存待回收的编号
            jedis.del(pendingCodesKey);
            if (pendingCodes != null && !pendingCodes.isEmpty()) {
                jedis.sadd(pendingCodesKey, pendingCodes.toArray(new String[0]));
            }
            
            // 清除并重新保存已回收的编号
            jedis.del(recycledCodesKey);
            if (recycledCodes != null && !recycledCodes.isEmpty()) {
                jedis.sadd(recycledCodesKey, recycledCodes.toArray(new String[0]));
            }
            
            logger.info("Successfully saved state to Redis with prefix: {}", keyPrefix);
            return true;
        } catch (Exception e) {
            logger.error("Failed to save state to Redis: {}", e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public CodeGeneratorState load() {
        try (Jedis jedis = jedisPool.getResource()) {
            // 检查键是否存在
            if (!jedis.exists(currentMaxValueKey)) {
                logger.warn("No state found in Redis with prefix: {}", keyPrefix);
                return null;
            }
            
            // 加载当前最大值
            String currentMaxValueStr = jedis.get(currentMaxValueKey);
            long currentMaxValue = Long.parseLong(currentMaxValueStr);
            
            // 加载已确认的编号
            Set<String> confirmedCodes = jedis.smembers(confirmedCodesKey);
            
            // 加载待回收的编号
            Set<String> pendingCodes = jedis.smembers(pendingCodesKey);
            
            // 加载已回收的编号
            Set<String> recycledCodes = jedis.smembers(recycledCodesKey);
            
            // 创建状态对象
            CodeGeneratorState state = new CodeGeneratorState();
            state.setCurrentMaxValue(currentMaxValue);
            state.setConfirmedCodes(confirmedCodes != null ? confirmedCodes : new HashSet<>());
            state.setPendingCodes(pendingCodes != null ? pendingCodes : new HashSet<>());
            state.setRecycledCodes(recycledCodes != null ? recycledCodes : new HashSet<>());
            
            logger.info("Successfully loaded state from Redis with prefix: {}, currentMaxValue: {}, confirmedCodes: {}, pendingCodes: {}, recycledCodes: {}",
                    keyPrefix, currentMaxValue, 
                    confirmedCodes != null ? confirmedCodes.size() : 0, 
                    pendingCodes != null ? pendingCodes.size() : 0, 
                    recycledCodes != null ? recycledCodes.size() : 0);
            
            return state;
        } catch (Exception e) {
            logger.error("Failed to load state from Redis: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public boolean clear() {
        try (Jedis jedis = jedisPool.getResource()) {
            // 删除所有键
            jedis.del(currentMaxValueKey, confirmedCodesKey, pendingCodesKey, recycledCodesKey);
            logger.info("Successfully cleared state in Redis with prefix: {}", keyPrefix);
            return true;
        } catch (Exception e) {
            logger.error("Failed to clear state in Redis: {}", e.getMessage(), e);
            return false;
        }
    }
}